<template>
  <div class="flex flex-col h-full">
    <!--    查询栏-->
    <el-card v-show="props.queryFilter && props.queryFilter.length > 0" shadow="hover" class="mb-8px query-card" :style="{'height': queryHeight }">
      <div ref="queryContentRef" class="flex flex-row justify-between">
        <el-form ref="queryFormRef" v-model="formData" :inline="true">

          <el-form-item :label="item.label" v-for="(item, index) in props.queryFilter" v-show="drawerQueryItem.includes(item.name)" :key="index" :prop="item.name" >
            <el-checkbox-group v-if="item.type === 'ElCheckbox'" v-model="formData[item.name]" v-bind="item.props">
              <el-checkbox v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :value="child.value">{{ child.label }}</el-checkbox>
            </el-checkbox-group>

            <el-radio-group v-else-if="item.type === 'ElRadio'" v-model="formData[item.name]" v-bind="item.props">
              <el-radio v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :value="child.value">{{ child.label }}</el-radio>
            </el-radio-group>

            <el-cascader v-else-if="item.type === 'ElCascader'" v-model="formData[item.name]" v-bind="item.props" clearable/>

            <el-date-picker v-else-if="item.type === 'ElDatePicker'" v-model="formData[item.name]" v-bind="item.props"/>

            <el-input v-else-if="item.type === 'ElInput'" v-model="formData[item.name]" v-bind="item.props"/>

            <el-input-number v-else-if="item.type === 'ElInputNumber'" v-model="formData[item.name]" />

            <el-select style="width: 180px" v-else-if="item.type === 'ElSelect'" v-model="formData[item.name]" v-bind="item.props" clearable>
              <el-option v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :label="child.label" :value="child.value">{{ child.label }}</el-option>
            </el-select>

            <el-switch v-else-if="item.type === 'ElSwitch'" v-model="formData[item.name]" v-bind="item.props"/>

          </el-form-item>
        </el-form>
        <div class="min-w-230px">
          <el-button @click="reset"><SvgIcon icon="ep:refresh" class="mr-4px" />重置</el-button>
          <el-button type="primary" @click="search"><SvgIcon icon="ep:search" class="mr-4px" />查询</el-button>
          <el-button link type="primary" @click="toggleQuery">展开
            <SvgIcon v-if="!fullQuery" class="fs-14 ml-2px" icon='ep:arrow-down' />
            <SvgIcon v-else class="fs-14 ml-2px" icon='ep:arrow-up' />
          </el-button>
        </div>
      </div>
    </el-card>
    <!--    表格-->
    <el-card shadow="hover" class="flex-1 table-card" body-class="h-full">
      <div style="height: calc(100% - 36px)">
        <vxe-grid ref="vxeTableRef" class="mytable-scrollbar" v-bind="props.table" :loading="loading" :data="tableData">
          <template #toolbarButtons>
            <el-button v-if="hasBtn('add')" type="success" @click="$emit('add')"><SvgIcon class="mr-4px" icon="ep:plus" />新增</el-button>
            <slot name="exToolbarButtons"></slot>
          </template>

          <template #action="{ row }">
            <el-button link v-if="hasBtn('detail')" @click="$emit('detail', row)"><SvgIcon class="mr-4px" icon="ep:view" />详情</el-button>
            <el-button link type="primary" v-if="hasBtn('edit')" @click="$emit('edit', row)"><SvgIcon class="mr-4px" icon="ep:edit"/>编辑</el-button>

            <el-dropdown class="ml-12px" v-if="(props.table?.operatorExBtn && authExOperaBtn(props.table?.operatorExBtn).length>0) || hasBtn('delete')" @command="(command: string) => handleCommand(command, row)">
              <el-button link>
                <SvgIcon icon="ep:more-filled"/>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="delete" v-if="hasBtn('delete')">
                    <SvgIcon icon="ep:delete" class="mr-4px fc-F56C6C" /><span class="fc-F56C6C">删除</span>
                  </el-dropdown-item>
                  <template v-for="(item, index) in props.table?.operatorExBtn" :key="index">
                    <el-dropdown-item v-if="hasBtn(item.auth, 'exBtn')" :command="item.name">
                      <SvgIcon v-if="item.icon" :icon="item.icon" class="mr-4px" />{{ item.label }}
                    </el-dropdown-item>
                  </template>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>

          <template v-for="(item, index) in slots" :key="index" v-slot:[item]="{ row }">
            <slot :name="item" v-bind="row"></slot>
          </template>
        </vxe-grid>
      </div>
      <div class="h-36px w-full flex justify-between items-center">
        <div><span class="text-sm _primary-color pl-6px"><slot name="tableUnit">单位：元</slot></span></div>
        <el-pagination v-show="props.pagination?.show" background v-bind="props.pagination" :total="total" v-model:page-size="pageSize" v-model:current-page="currentPage" />
      </div>
    </el-card>
    <!--    侧边栏-->
    <el-drawer class="_table-drawer" v-model="drawer" title="高级查询" size="50%">
      <div class="pt-20px px-20px">
        <TitleDrawer title="显示项（最多勾选 4 个，显示效果最佳）"/>
        <div class="px-12px mb-12px">
          <el-checkbox-group v-model="drawerQueryItem" :min="1">
            <el-checkbox v-for="(item, index) in totalQuery" :key="index" :value="item.name">{{ item.label }}</el-checkbox>
          </el-checkbox-group>
        </div>
      </div>
      <el-divider class="!my-12px" />
      <div class="px-20px">
        <TitleDrawer title="查询项"/>
        <el-form ref="drawerFormRef" v-model="formData" label-width="80px">
          <el-row>
            <el-col :span="12" v-for="(item, index) in props.queryFilter" :key="index">
              <el-form-item :label="item.label" :prop="item.name" >
                <el-checkbox-group v-if="item.type === 'ElCheckbox'" v-model="formData[item.name]" v-bind="item.props">
                  <el-checkbox v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :value="child.value">{{ child.label }}</el-checkbox>
                </el-checkbox-group>

                <el-radio-group v-else-if="item.type === 'ElRadio'" v-model="formData[item.name]" v-bind="item.props">
                  <el-radio v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :value="child.value">{{ child.label }}</el-radio>
                </el-radio-group>

                <el-cascader v-else-if="item.type === 'ElCascader'" v-model="formData[item.name]" v-bind="item.props" clearable/>

                <el-date-picker v-else-if="item.type === 'ElDatePicker'" v-model="formData[item.name]" v-bind="item.props"/>

                <el-input v-else-if="item.type === 'ElInput'" v-model="formData[item.name]" v-bind="item.props"/>

                <el-input-number v-else-if="item.type === 'ElInputNumber'" v-model="formData[item.name]" />

                <el-select style="width: 180px" v-else-if="item.type === 'ElSelect'" v-model="formData[item.name]" v-bind="item.props" clearable>
                  <el-option v-for="(child, childIndex) in item.options" v-bind="child.props" :key="childIndex" :label="child.label" :value="child.value">{{ child.label }}</el-option>
                </el-select>

                <el-switch v-else-if="item.type === 'ElSwitch'" v-model="formData[item.name]" v-bind="item.props"/>

              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <template #footer>
        <div class="flex justify-between px-20px">
          <el-button @click="save"><SvgIcon icon="hugeicons:task-edit-01" class="mr-4px" />保存配置</el-button>
          <div>
            <el-button type="primary" @click="search"><SvgIcon icon="ep:search" class="mr-4px" />查询</el-button>
            <el-button @click="reset"><SvgIcon icon="ep:refresh" class="mr-4px" />重置</el-button>
          </div>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, useTemplateRef, computed, watch, reactive, onMounted, nextTick } from 'vue'
import { useElementSize } from '@vueuse/core'
import type { IProps, operatorExBtn, query, VxeTableProps } from './prop.ts'
import { defaultProps } from './prop.ts'
import { getTableData } from '@/api/table/table.ts'
import { ElMessage, ElMessageBox } from 'element-plus'
import { intersection, differenceBy } from 'lodash'
import { type VxeGridInstance } from 'vxe-table'
import type { FormInstance } from 'element-plus'
import { userStore } from '@/stores/user.ts'
import { setLocalItem, getLocalItem } from '@/utils/storage/index.ts'
import TitleDrawer from '@/components/TitleDrawer/TitleDrawer.vue'

const user = userStore()
const emit = defineEmits(['add', 'edit', 'detail', 'delete', 'event'])

onMounted(() => {
  const formKey = (user.userInfo.id || '' ) + props.table!.id + 'form'
  const checkKey = (user.userInfo.id || '' ) + props.table!.id + 'check'
  const formVal = getLocalItem(formKey)
  const checkVal = getLocalItem(checkKey)
  if (formVal) {
    formData.value = formVal
  }
  if (checkVal) {
    drawerQueryItem.value = checkVal
  }
  if (exProp.table && exProp.table.url && exProp.table.autoLoad) {
    load()
  }
})

// 插槽
const slots = ref<Array<any>>([])

const loading = ref<boolean>(false)
const tableData = ref()
// 分页
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
watch([currentPage, pageSize], () => {
  load()
})
// prop
const exProp = defineProps<IProps>()
const props = reactive<IProps>({ ...defaultProps })
// 根据权限校验拥有的额外按钮
const authExOperaBtn = (operatorExBtn: Array<operatorExBtn> | undefined) => {
  if (!operatorExBtn) {
    return [];
  }
  return operatorExBtn.filter(item => user.hasPerms(item.auth))
}
// 按钮权限
const hasBtn = (name, type = 'default') => {
  if (type === 'default') {
    if (!props.table || !props.table.defaultBtn) {
      return false
    }
    if (props.table && props.table.defaultBtn && Array.isArray(props.table.defaultBtn)) {
      // 数组方式入参，根据传入按钮名称确定是否显示
      return props.table.defaultBtn.includes(name)
    } else {
      // 对象方式入参，不仅需要校验是否传入，还需要校验是否拥有权限。
      return props.table.defaultBtn[name] && user.hasPerms(props.table.defaultBtn[name])
    }
  } else {
    if (props.table?.operatorExBtn && Array.isArray(props.table.operatorExBtn)) {
      return user.hasPerms(name)
    } else {
      return false
    }
  }
}
// 计算操作列宽度 todo zpd 待优化，后续需要考虑到操作列按钮动态补位情况
const computedOperatorWidth = (config: VxeTableProps) => {
  let width = 0;
  let btnCount = 0
  if (config && config.operatorColumn) {
    if (Array.isArray(config.defaultBtn)) {
      btnCount = intersection(config.defaultBtn, ['edit', 'detail']).length
    } else if (config.defaultBtn) {
      const keys = Object.keys(config.defaultBtn).filter(key => user.hasPerms(config.defaultBtn![key]))
      btnCount = intersection(keys, ['edit', 'detail']).length
    }
    width = btnCount * 64
  }
  const btn = authExOperaBtn(config.operatorExBtn)
  if (btn.length > 0 || hasBtn('delete')) {
    width += (60 - 10*btnCount)
  }
  return width
}

// 查询栏
const queryContentRef = useTemplateRef('queryContentRef')
const { height } = useElementSize(queryContentRef)
const fullQuery = ref(false)
const toggleQuery = () => {
  if (props.queryConfig?.type === 'default') {
    fullQuery.value = !fullQuery.value
  } else if (props.queryConfig?.type === 'drawer') {
    drawer.value = !drawer.value
  }
}
const formData = ref({})
const queryFormRef = useTemplateRef<FormInstance>('queryFormRef')
const drawerFormRef = useTemplateRef<FormInstance>('drawerFormRef')
const search = () => {
  currentPage.value = 1
  load()
}
const reset = () => {
  queryFormRef.value?.resetFields()
  drawerFormRef.value?.resetFields()
  formData.value = {}
  search()
}
const queryHeight = computed(() => {
  return fullQuery.value ? (height.value + 22)+'px' : '53px'
})
// 表格
const vxeTableRef = useTemplateRef<VxeGridInstance>('vxeTableRef')
const load = async () => {
  await nextTick()
  loading.value = true
  let params = {
    page: currentPage.value,
    pageSize: pageSize.value,
  }
  params = Object.assign(params, formData.value)
  if (props.exParams) {
    params = Object.assign(params, props.exParams)
  }
  Object.keys(params).forEach((key) => {
    if (Array.isArray(params[key])) {
      params[key] = params[key].join(',')
    }
  })
  if (!props.table || !props.table.url) {
    ElMessage.error('table url为空请配置请求地址')
    loading.value = false
    return
  }
  try {
    const { data } = await getTableData(props.table.url, params)
    const { total: sum, records } = data
    total.value = sum
    tableData.value = records
  } catch {
    tableData.value = []
    total.value = 0
    currentPage.value = 1
  } finally {
    loading.value = false
  }
}
// 获取单选框
const getRadioEvent = () => {
  return vxeTableRef.value?.getRadioRecord()
}
// 清空单选
const clearRadioRowEvent = () => {
  vxeTableRef.value?.clearRadioRow()
}
// 获取复选
const getSelectEvent = () => {
  return vxeTableRef.value?.getCheckboxRecords()
}
const clearSelectEvent = () => {
  vxeTableRef.value?.clearCheckboxRow()
}
const handleCommand = (command: string, row: any) => {
  if (command === 'delete') {
    ElMessageBox.confirm('确认删除该数据吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      emit('delete', row)
    })
  } else {
    emit('event', {command, row})
  }
}
// 侧边栏
const drawer = ref(false)
const drawerQueryItem = ref<Array<string>>([])
const totalQuery = ref<Array<query>>()
const save = () => {
  const formKey = (user.userInfo.id || '' ) + props.table!.id + 'form'
  const checkKey = (user.userInfo.id || '' ) + props.table!.id + 'check'
  setLocalItem(formKey, formData.value)
  setLocalItem(checkKey, drawerQueryItem.value)
  ElMessage.success('保存成功')
}
// 监听
watch(() => exProp.table, (newVal) => {
  // console.log('监听到表格变动')
  props.table = Object.assign({}, { ...props.table}, {...newVal})
  if (props.table.columns) {
    slots.value.splice(0, slots.value.length)
    props.table.columns.forEach(column => {
      if(column.slots && column.slots.default && column.slots.default !== 'action') {
        slots.value.push(column.slots.default as string)
      }
    })
  }
  if (props.table.operatorColumn && props.table.columns) {
    const hasAction = props.table.columns.filter(item => item.field === 'action')
    if (hasAction.length === 0) {
      props.table.columns.push({
        field: 'action',
        title: '操作',
        width: computedOperatorWidth(props.table),
        fixed: 'right',
        slots: {
          default: 'action'
        }
      })
    }
  }
}, {immediate: true, deep: true})
watch(() => exProp.queryFilter, (newVal) => {
  // console.log('监听到过滤变动')
  totalQuery.value = newVal
  if (!newVal) {
    drawerQueryItem.value = drawerQueryItem.value.splice(0, drawerQueryItem.value.length)
    props.queryFilter = []
    return
  }
  if (drawerQueryItem.value.length === 0) {
    props.queryFilter = newVal
    props.queryFilter?.forEach((item: query) => {
      if (!drawerQueryItem.value.includes(item.name)) {
        drawerQueryItem.value.push(item.name)
      }
    })
  } else {
    // 新增筛选项
    newVal.filter(item => !drawerQueryItem.value.includes(item.name))
      .forEach((item: query) => {
        drawerQueryItem.value.push(item.name)
        props.queryFilter?.push(item)
      })
    // 删除筛选项
    const removeItem = differenceBy(props.queryFilter, newVal, 'name')
    removeItem.forEach(item => {
      drawerQueryItem.value.splice(drawerQueryItem.value.indexOf(item.name), 1)
      props.queryFilter?.splice(props.queryFilter.indexOf(item), 1)
    })
  }
}, {immediate: true, deep: true})
watch(() => exProp.pagination, (newVal) => {
  // console.log('监听到分页变动', exProp.table.id, newVal)
  if (newVal) {
    props.pagination = Object.assign({}, {...props.pagination}, {...newVal})
  } else {
    props.pagination = defaultProps.pagination
  }
}, {immediate: true})
watch(() => exProp.exParams, (newVal) => {
  // console.log('监听到参数变动')
  if (newVal) {
    props.exParams = Object.assign({}, {...props.exParams}, {...newVal})
  } else {
    props.exParams = defaultProps.exParams
    console.log(defaultProps.exParams)
  }
}, {immediate: true})
watch(() => exProp.queryConfig, (newVal) => {
  // console.log('监听到查询配置变动')
  if (newVal) {
    props.queryConfig = Object.assign({}, {...props.queryConfig}, {...newVal})
  } else {
    props.queryConfig = defaultProps.queryConfig
  }
}, {immediate: true})
defineExpose({
  load,
  getRadioEvent,
  clearRadioRowEvent,
  getSelectEvent,
  clearSelectEvent,
  vxeTableRef
})
</script>

<style>
._table-drawer {
  --el-drawer-padding-primary: 0px;
}
.vxe-grid--layout-body-content-wrapper {
  overflow: hidden;
}
.table-card {
  --el-card-padding: 2px 10px 0 10px;
}
.query-card {
  --el-card-padding: 10px 20px 0 20px;
}
.mytable-scrollbar {
  ::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }
  ::-webkit-scrollbar-thumb {
    border-radius: 4px;
  }
}

/** 默认模式 */
[data-vxe-ui-theme="light"] {
  .mytable-scrollbar {
    ::-webkit-scrollbar-track,
    ::-webkit-scrollbar-corner {
      background-color: #FFFFFF;
    }
    ::-webkit-scrollbar-thumb {
      background-color: #bfbfbf;
    }
    ::-webkit-scrollbar-thumb:hover,
    ::-webkit-scrollbar-thumb:active {
      background-color: #787878;
    }
  }
}

/** 暗黑模式 */
[data-vxe-ui-theme="dark"] {
  .mytable-scrollbar {
    ::-webkit-scrollbar-track,
    ::-webkit-scrollbar-corner {
      background-color: #151518;
    }
    ::-webkit-scrollbar-thumb {
      background-color: #bfbfbf;
    }
    ::-webkit-scrollbar-thumb:hover,
    ::-webkit-scrollbar-thumb:active {
      background-color: #A3A6AD;
    }
  }
}
</style>